Skip to content

Use O_CLOEXEC to avoid race conditions#10162

Open
embhorn wants to merge 1 commit intowolfSSL:masterfrom
embhorn:gh9753
Open

Use O_CLOEXEC to avoid race conditions#10162
embhorn wants to merge 1 commit intowolfSSL:masterfrom
embhorn:gh9753

Conversation

@embhorn
Copy link
Copy Markdown
Member

@embhorn embhorn commented Apr 8, 2026

Description

Use the "close-on-exec" flag at file creation time to harden multithread use cases against race conditions.

Fixes #9753

Testing

build testing

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

@embhorn embhorn self-assigned this Apr 8, 2026
@embhorn embhorn added the Not For This Release Not for release 5.9.1 label Apr 8, 2026
Copilot AI review requested due to automatic review settings April 8, 2026 12:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Hardens file-descriptor creation against FD leaks across fork()+exec() in multithreaded programs by using close-on-exec flags (e.g., O_CLOEXEC, SOCK_CLOEXEC, EFD_CLOEXEC) at creation time where possible.

Changes:

  • Introduces portable WC_*_CLOEXEC macros that fall back to no-ops on unsupported platforms.
  • Applies WC_CLOEXEC / WC_SOCK_CLOEXEC / WC_EFD_CLOEXEC to various open(), socket(), and eventfd() call sites.
  • Uses accept4(..., SOCK_CLOEXEC) for AF_ALG where available and passes close-on-exec flag to perf_event_open.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
wolfssl/wolfcrypt/wc_port.h Adds portable close-on-exec flag macros for FD-creating syscalls.
wolfcrypt/src/random.c Opens RNG-related device FDs with O_CLOEXEC where available.
wolfcrypt/src/port/intel/quickassist_mem.c Opens QAT memory device with O_CLOEXEC.
wolfcrypt/src/port/devcrypto/wc_devcrypto.c Opens /dev/crypto with O_CLOEXEC.
wolfcrypt/src/port/caam/wolfcaam_qnx.c Opens CAAM device with O_CLOEXEC.
wolfcrypt/src/port/af_alg/wc_afalg.c Uses accept4(..., SOCK_CLOEXEC) when available; creates AF_ALG sockets with SOCK_CLOEXEC.
wolfcrypt/src/port/af_alg/afalg_hash.c Uses accept4(..., SOCK_CLOEXEC) when available for duplicated AF_ALG FDs.
wolfcrypt/benchmark/benchmark.c Adds PERF_FLAG_FD_CLOEXEC to perf_event_open flags.
src/wolfio.c Creates TCP sockets with SOCK_CLOEXEC; sets FD_CLOEXEC after accept().
src/ssl.c Creates EGD AF_UNIX socket with SOCK_CLOEXEC.
src/crl.c Uses CLOEXEC flags for eventfd/inotify/open() in CRL monitor paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wolfcrypt/benchmark/benchmark.c
Comment thread src/wolfio.c Outdated
Comment thread src/wolfio.c Outdated
Comment thread wolfcrypt/src/port/af_alg/wc_afalg.c Outdated
Copilot AI review requested due to automatic review settings April 8, 2026 13:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wolfssl/wolfcrypt/wc_port.h Outdated
Comment thread wolfcrypt/benchmark/benchmark.c Outdated
Comment thread src/wolfio.c Outdated
Comment thread src/wolfio.c Outdated
Comment thread src/crl.c
@embhorn embhorn assigned wolfSSL-Bot and unassigned embhorn Apr 9, 2026
Copy link
Copy Markdown
Contributor

@dgarske dgarske left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐺 Skoll Code Review

Overall recommendation: REQUEST_CHANGES
Findings: 5 total — 4 posted, 1 skipped

Posted findings

  • [Low] crl.c kqueue path: F_SETFD without read-modify-writesrc/crl.c:1719
  • [Low] wolfio.c: defined(SOCK_CLOEXEC) guard in accept4 path is tautologically truesrc/wolfio.c:1642-1643
  • [Medium] afalg_hash.c: accept4 used without _GNU_SOURCE but guarded by system SOCK_CLOEXECwolfcrypt/src/port/af_alg/afalg_hash.c:226-232
  • [High] wolfio.c: _GNU_SOURCE placement may conflict if libwolfssl_sources.h pulls in system headerssrc/wolfio.c:31-36
Skipped findings
  • [Medium] wc_afalg.c: SOCK_CLOEXEC fallback defeats accept4 guard — missing _GNU_SOURCE

Review generated by Skoll via openclaw

Comment thread src/crl.c Outdated
Comment thread src/wolfio.c Outdated
Comment thread wolfcrypt/src/port/af_alg/afalg_hash.c Outdated
Comment thread src/wolfio.c Outdated
Copilot AI review requested due to automatic review settings April 10, 2026 18:33

This comment was marked as outdated.

@embhorn embhorn removed the Not For This Release Not for release 5.9.1 label Apr 10, 2026
Copilot AI review requested due to automatic review settings April 13, 2026 19:34

This comment was marked as outdated.

Copy link
Copy Markdown

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10162

Scan targets checked: wolfcrypt-api_misuse, wolfcrypt-bugs, wolfcrypt-compliance, wolfcrypt-concurrency, wolfcrypt-consttime, wolfcrypt-defaults, wolfcrypt-mutation, wolfcrypt-port, wolfcrypt-port-bugs, wolfcrypt-portability, wolfcrypt-proptest, wolfcrypt-src, wolfcrypt-zeroize, wolfssl-bugs, wolfssl-compliance, wolfssl-consttime, wolfssl-defaults, wolfssl-mutation, wolfssl-proptest, wolfssl-src, wolfssl-zeroize

Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread wolfcrypt/src/port/caam/wolfcaam_qnx.c Outdated
Comment thread src/wolfio.c
Comment thread src/ssl.c
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/wolfio.c Outdated
Comment thread src/ssl.c Outdated
Comment thread wolfcrypt/src/port/devcrypto/wc_devcrypto.c Outdated
Comment thread wolfcrypt/src/port/intel/quickassist_mem.c Outdated
Comment thread wolfcrypt/src/port/caam/wolfcaam_qnx.c Outdated
Copy link
Copy Markdown

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10162

Scan targets checked: wolfcrypt-api_misuse, wolfcrypt-bugs, wolfcrypt-compliance, wolfcrypt-concurrency, wolfcrypt-consttime, wolfcrypt-defaults, wolfcrypt-mutation, wolfcrypt-port, wolfcrypt-port-bugs, wolfcrypt-portability, wolfcrypt-proptest, wolfcrypt-src, wolfcrypt-zeroize, wolfssl-bugs, wolfssl-compliance, wolfssl-consttime, wolfssl-defaults, wolfssl-mutation, wolfssl-proptest, wolfssl-src, wolfssl-zeroize

No new issues found in the changed files. ✅

@embhorn embhorn removed their assignment Apr 14, 2026
SparkiDev
SparkiDev previously approved these changes Apr 14, 2026
dgarske
dgarske previously approved these changes Apr 16, 2026
Copy link
Copy Markdown
Contributor

@dgarske dgarske left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@douzzer please look these over as well.

@dgarske dgarske assigned douzzer and unassigned dgarske Apr 16, 2026
@dgarske dgarske requested a review from douzzer April 16, 2026 22:48
Copy link
Copy Markdown
Contributor

@douzzer douzzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be a lot cleaner+nicer to take the wc_open_cloexec() added in random.c, move it to wc_port.c, make it a WOLFSSL_LOCAL, and use it everywhere consistently.

While you're at it, it would make sense to add other syscall wrappers for calls used over and over with CLOEXEC -- probably accept(), probably others.

@douzzer douzzer assigned embhorn and unassigned douzzer Apr 16, 2026
@embhorn embhorn dismissed stale reviews from dgarske and SparkiDev via 7aab6e5 April 17, 2026 14:38
Copilot AI review requested due to automatic review settings April 17, 2026 15:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1865 to +1878
WOLFSSL_LOCAL void wc_set_cloexec(int fd);
WOLFSSL_LOCAL int wc_open_cloexec(const char* path, int flags);
WOLFSSL_LOCAL int wc_socket_cloexec(int domain, int type, int protocol);
WOLFSSL_LOCAL int wc_accept_cloexec(int sockfd, void* addr, void* addrlen);
#else
/* Platforms without POSIX close-on-exec semantics (Windows, OS/2 OW,
* Linux kernel module, Zephyr, etc.): pass through to plain syscalls
* where the underlying headers are available in the caller. */
#define wc_set_cloexec(fd) ((void)(fd))
#define wc_open_cloexec(path, flags) open((path), (flags))
#define wc_socket_cloexec(domain, type, protocol) \
socket((domain), (type), (protocol))
#define wc_accept_cloexec(sockfd, addr, addrlen) \
accept((sockfd), (addr), (addrlen))
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wc_open_cloexec(const char* path, int flags) cannot correctly represent open() calls that require a third mode_t argument (e.g., when flags contains O_CREAT). Additionally, the non-POSIX passthrough macro always expands to a 2-argument open(path, flags). Consider changing wc_open_cloexec to accept an optional mode (e.g., a variadic interface that forwards mode when needed, or a separate wc_open_cloexec_mode(path, flags, mode)), so the helper is safe for all open() use cases.

Copilot uses AI. Check for mistakes.
Comment thread wolfcrypt/src/wc_port.c
Comment on lines +5191 to +5202
int wc_accept_cloexec(int sockfd, void* addr, void* addrlen)
{
int fd;
#if defined(__linux__) || defined(__ANDROID__)
fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen,
SOCK_CLOEXEC);
if (fd >= 0)
return fd;
if (errno != ENOSYS && errno != EINVAL)
return fd;
#endif
fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using void* for addr/addrlen removes type checking and forces casts at every callsite/implementation, which can hide real signature mismatches across platforms. Prefer a typed signature (e.g., struct sockaddr* and socklen_t* for the POSIX implementation) and, where Windows differs, provide a platform-specific overload via macro/inline wrapper using the platform socket-length type. This will also help prevent incorrect casts like the one currently needed in wolfio.c.

Suggested change
int wc_accept_cloexec(int sockfd, void* addr, void* addrlen)
{
int fd;
#if defined(__linux__) || defined(__ANDROID__)
fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen,
SOCK_CLOEXEC);
if (fd >= 0)
return fd;
if (errno != ENOSYS && errno != EINVAL)
return fd;
#endif
fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
int wc_accept_cloexec(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
{
int fd;
#if defined(__linux__) || defined(__ANDROID__)
fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
if (fd >= 0)
return fd;
if (errno != ENOSYS && errno != EINVAL)
return fd;
#endif
fd = accept(sockfd, addr, addrlen);

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: many open() without O_CLOEXEC

7 participants